﻿// Copyright (c)  MOKEYISH. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Text;
using NSQL.Expressions;
using NSQL.Expressions.Functions;
using NSQL.Generator.Formatters;
using NSQL.LogicalResource;
using NSQL.Statements;

namespace NSQL.Generator
{
    public class MySqlGenerator : BaseGenerator, IExpressionVisitor<StringBuilder>
    {
        protected string If => Format(nameof(If));
        protected string IfNUll => Format(nameof(IfNUll));
        protected override string PadLeft => Format("LPad");
        protected override string PadRight => Format("RPad");
        
        protected override string TrimStart => Format("LTrim");
        protected override string TrimEnd => Format("RTrim");
        
        protected override StringBuilder FormatSelect(StringBuilder @select, StringBuilder @from, StringBuilder @where, StringBuilder @group,
            StringBuilder order, StringBuilder having, int skip, int limit)
        {
            var buidler = FormatSelect(@select, @from, @where, @group, order, having);
            
            if (skip <= 0 && limit <= 0) return buidler;
            
            buidler.Append(' ');
            buidler.Append(Limit);
            buidler.Append(' ');
            buidler.Append(skip >= 0 ? skip : 0);
            if (limit <= 0) return buidler;
            buidler.Append(", ");
            buidler.Append(limit);
            return buidler;
        }
        
        StringBuilder IFunctionVisitor<StringBuilder>.Visit(INvlFunction nvlFunction)
        {
            var builder = new StringBuilder();
            var hasThen = !(nvlFunction.Then is null);

            if (hasThen)
            {
                builder.Append(If);
                builder.Append('(');
                builder.Append(nvlFunction.Expr.Accept(this));
                builder.Append(' ').Append(Is);
                builder.Append(' ').Append(Null);
                builder.Append(", ").Append(nvlFunction.Default.Accept(this));
                builder.Append(", ").Append(nvlFunction.Then.Accept(this));
                builder.Append(')');
            }
            else
            {
                builder.Append(IfNUll);
                builder.Append('(');
                builder.Append(nvlFunction.Expr.Accept(this));
                builder.Append(", ").Append(nvlFunction.Default.Accept(this));
                builder.Append(')');
            }
            return builder;
        }
        

        public MySqlGenerator(SqlGeneratorSettings settings) : base(settings)
        {
        }
    }
    
    public static class MySqlGeneratorExtensions
    {
        public static string ToMySql(this IStatement statement, SqlGeneratorSettings settings = null)
        {
            return new MySqlGenerator(settings ?? new SqlGeneratorSettings()
            {
                KeywordStyle = KeywordStyle.LowerCase
            }).Generate(statement);
        }
        public static string ToMySql(this IStatement statement, ILogicalDatabase database)
        {
            return new MySqlGenerator(new SqlGeneratorSettings
            {
                Database = database,
                KeywordStyle = KeywordStyle.LowerCase
            }).Generate(statement);
        }
    }
}